package physicstester;
import static org.junit.Assert.*;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import objects.*;
import org.junit.*;

import assets.*;
import physics.*;
import physics.Vector;
import template.*;

public class TestPhysics implements KeyListener {

	boolean run = true;
	double prevTime, curTime;
	double prevXDist, curXDist, prevYDist, curYDist;


	Screen screen;
	Draw drawObjects = new Draw();
	PhysXProcessor physics = new PhysXProcessor();
	ArrayList<BasicShape> objects = new ArrayList<BasicShape>();
	ArrayList<BasicShape> borderObjects = new ArrayList<BasicShape>();
	Graphics2D graphics;
	@Before
	public void setUp() throws Exception {
		Run();
	}

	private static final DisplayMode possibleModes[] = {
		new DisplayMode(1360, 768, 32, 0),
		new DisplayMode(800, 600, 32, 0),
		new DisplayMode(800, 600, 24, 0),
		new DisplayMode(800, 600, 16, 0),
		new DisplayMode(640, 480, 32, 0),
		new DisplayMode(640, 480, 24, 0),
		new DisplayMode(640, 480, 16, 0),
		
	};
	///////////////////////////////////////////////////////////////////////////
	public void Inititialize() 
	{
		// .. This is where I'd imagine we load images(sprites) and set any static values
		Window window = screen.getFullScreenWindow();
		window.addKeyListener(this);
		objects.add(new BasicShape("Circle", new Vector(100, 100), 40, new Vector(0, 0)));
		objects.add(new BasicShape("Circle", new Vector(30, 200), 40, new Vector(0, 0)));
		objects.add(new BasicShape("Circle", new Vector(700, 30), 40, new Vector(0, 0)));
		objects.add(new BasicShape("Circle", new Vector(900, 20), 40, new Vector(0, 0)));
		objects.add(new BasicShape("Circle", new Vector(1000, 675), 40, new Vector(0, 0)));
		
		borderObjects.add(new BasicShape("Circle", new Vector(650, 83), 40, new Vector(5, 0), "Red"));
		borderObjects.add(new BasicShape("Circle", new Vector(950, 96), 40, new Vector(-2, 0), "Red"));
		borderObjects.add(new BasicShape("Circle", new Vector(1050, 89), 40, new Vector(10, 0), "Red"));
	}	
	
	public void Run()
	{

		screen = new Screen();
		try
		{
			DisplayMode displayMode = screen.FindCompatibleMode(possibleModes); // this is where we find our screen
			screen.setFullScreen(displayMode);
			Inititialize();
			GameLoop(); // Coded in here is everything that changes(logic, redrawing, etc...)
		}
		finally 
		{
			screen.RestoreScreen();
		}
		
	}
	
	public void GameLoop()
	{
	
		while (run) // For now we can manually tell the game to stop using esc key or something
		{

			graphics = screen.getGraphics();
			
			if (objects.size() > 0)
			{	
			    try {
			    	graphics.clearRect(0, 0, (int) screen.getWidth(), (int) screen.getHeight());
					testBorderControl();
					testCreation();
					testNoNullList();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			    
			}
			else
				graphics.clearRect(0, 0, screen.getWidth(), screen.getHeight());

			
			graphics.dispose(); // garbage
			screen.update();
			
			try 
			{
				Thread.sleep(3);
			} catch (Exception exception) {}
		}
	}
	
	
	public void stop() { run = false; }
	
	@Override
	public void keyPressed(KeyEvent event) 
	{
		// TODO Auto-generated method stub
		int key = event.getKeyCode();
		if (key == KeyEvent.VK_ESCAPE)
			stop();
	
			
		
	}

	@Override
	public void keyReleased(KeyEvent event) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyTyped(KeyEvent event) {
		// TODO Auto-generated method stub
		
	}
	
	@Test
	public void testCreation() throws Exception 
	{
		physics.handleEvents(objects);
	    drawObjects.drawObjects(objects, graphics);	
		for (int i = 0; i < objects.size(); i++)
		{
			if (Math.abs(objects.get(i).getAcceleration().getY()) > 1)
				fail("initial acceleration innaccurate");
			else 
				assertEquals(0, (int) objects.get(i).getAcceleration().getY());
		
			if (Math.abs(objects.get(i).getAcceleration().getX()) > 0 || Math.abs(objects.get(i).getAcceleration().getX()) < 0)
				fail("initial acceleration innaccurate");
			else 
				assertEquals(0, (int) objects.get(i).getAcceleration().getX());
		}
	}
	
	@Test
	public void testBorderControl() throws Exception
	{
		physics.handleEvents(borderObjects);
	    drawObjects.drawObjects(borderObjects, graphics);	
	    
	    for (int i = 0; i < objects.size(); i++)
	    {
	    	if (objects.get(i).getPosition().getX() + objects.get(i).getDiameter() > screen.getWidth())
	    		fail("Object surpassed border of screen");
	    	if (objects.get(i).getPosition().getX() < 0)
	    		fail("Object surpassed border of screen");
	    	if (objects.get(i).getPosition().getY() + objects.get(i).getDiameter() > screen.getHeight())
	    		fail("Object surpassed border of screen");
	    	if (objects.get(i).getPosition().getY() < 0)
	    		fail("Object surpassed border of screen");
	    	testNoNullList();
	    }
		
	}
	
	@Test
	public void testNoNullList() throws Exception
	{
		if (objects == null)
			fail("This list should never be null");
		if (borderObjects == null)
			fail("This list should never be null");
	}



}
